#pragma  once

//
// Created by xietianqi on 2025/1/12.
//

#include "RadixTree.h"

#include "../../Common.h"

/**
 * 按页数进行映射的 一页是8KB
 * 1page
 * 2page
 * 3page
 * ... page
 * 128page
 * 快速按照我需要的page数找返回一个K页的span节点
 * 需要加锁且不能是筒锁
 * 且要有一个全局唯一的PageCache
 * 一开始像系统申请128页的span
 * 要几页的span就用128页去减剩下几页的span就挂载第几个筒上
 */
class PageCache {
public:
//    void Insert() {
//
//    }
    Span* NewSpan(size_t k);
    static PageCache* GetInstance(){
        return &_sInstance;
    }
    PageCache& operator= (const PageCache& pageCache) = delete;
    PageCache(const PageCache& pageCache) = delete;
    std::mutex _pageMtx;

    Span* MapObjectToSpan(void * obj);

    void ReleaseSpanToPageCache(Span *pSpan);

private:
    /**
     * 页号和对应的span进行映射而页号是可以通过地址算到的,在我从大span切的时候就要初始化它,也就是链到链表上就要算
     *  合并后delete掉这个span是不是也应该删除映射啊
     */
    //std::unordered_map<PAGE_ID,Span*> _idSpanMap; // 使用基数树优化,底层是树结构或者哈希桶他在旋转操作在改动结构
    /* 
    * 这个是首先开好了页号映射空间在增改的时候不会去动数据结构
    * 只有在这两个函数ReleaseSpanToPageCache和NewSpan的时候会去写这个map 并且不可能写到同一个地方去
    * 读写是分离的线程1对一个位置读写的时候线程2不可能对这个位置读写
    */
    TCMalloc_PageMap2<BITS - PAGE_SHIFT> _idSpanMap;
    PageCache()=default;
    SpanList _spanLists[NPAGES];
    static PageCache _sInstance;
    // 定长内存池
    ObjectPool<Span> _spanPool;
};
